package com.example.demo.interceptors;

import com.auth0.jwt.interfaces.Claim;
import com.example.demo.error.ForbiddenException;
import com.example.demo.error.Unauthentication;
import com.example.demo.util.JwtToken;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Optional;
@Component
public class PermissionInterceptor extends HandlerInterceptorAdapter {
/*
* 拦截器逻辑
*
*  - 1 获取到请求token
*  - 2 验证token
*  - 3 获取 scope
*  - 4 读取 API @ScopeLevel
*  - 5 通过scopelevel 等级来决定是否能访问
*
*
*  */
    public PermissionInterceptor() {
        super();
    }

    @Override//用于决定是否放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Optional<Scopelevel> scopelevel = this.getScopeLevel(handler);
       if(!scopelevel.isPresent()){
           return true;
       }
       //huoqu 获取request里的token
        String token  = request.getHeader("Authorization");
       if(StringUtils.isEmpty(token)){
           throw new Unauthentication(10004);//新建的异常
       }

       //查看是否是Bearer 标准的令牌

        if(!token.startsWith("Bearer")){
            throw new Unauthentication(10004);
        }
        String jwtToken = token.split(" ")[1];
        Optional<Map<String,Claim>> optionalmap = JwtToken.getClaims(token);

        //获取真实的值 接收空值
        Map<String,Claim> map = optionalmap.orElseThrow(()->new Unauthentication(10004));
//比对scoplelevel
        boolean valid = this.hasPermission(scopelevel.get(),map);

        return valid;
    }
//比对scoplelevel函数 验证是否满足权限
    private boolean hasPermission (Scopelevel scopelevel,Map<String,Claim> map){
        Integer level = scopelevel.Value();
        Integer scope = map.get("scope").asInt();//数据转移方法

        if(level > scope){
            throw new ForbiddenException(10005);
            //不允许访问  权限不够
        }
        //权限足够 直接返回真值
        return true ;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override//用于清理资源
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    //用来对付scope读取
    private Optional<Scopelevel> getScopeLevel(Object handler){
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            Scopelevel scope = handlerMethod.getMethod().getAnnotation(Scopelevel.class);
            if(scope ==null){
                return Optional.empty();
            }
            return Optional.of(scope);
        }

        return Optional.empty() ;

    }


}
